package com.blog.cmrpersonalblog.controller;

import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.stp.StpUtil;
import com.blog.cmrpersonalblog.annotation.RateLimit;
import com.blog.cmrpersonalblog.common.PageResult;
import com.blog.cmrpersonalblog.common.Result;
import com.blog.cmrpersonalblog.dto.article.request.ArticleCommentListRequest;
import com.blog.cmrpersonalblog.dto.article.response.ArticleCommentResponse;
import com.blog.cmrpersonalblog.dto.comment.request.CommentCreateRequest;
import com.blog.cmrpersonalblog.dto.comment.request.CommentLikeRequest;
import com.blog.cmrpersonalblog.dto.comment.request.CommentTreeRequest;
import com.blog.cmrpersonalblog.dto.comment.responst.CommentImageInfo;
import com.blog.cmrpersonalblog.dto.comment.responst.CommentImageUploadResponse;
import com.blog.cmrpersonalblog.dto.comment.responst.CommentLikeResponse;
import com.blog.cmrpersonalblog.dto.comment.responst.CommentStatsResponse;
import com.blog.cmrpersonalblog.enums.LimitType;
import com.blog.cmrpersonalblog.service.UserCommentService;
import com.blog.cmrpersonalblog.service.CommentImageService;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
import java.util.Map;

/**
 * 用户端评论控制器
 * 提供文章评论的查看、创建、点赞、回复等功能
 */
@Slf4j
@RestController
@RequestMapping("/api/comments")
@CrossOrigin(origins = "*", maxAge = 3600)
@Validated
public class UserCommentController {

   @Resource
    private UserCommentService userCommentService;

   @Resource
    private CommentImageService commentImageService;

    /**
     * 获取文章评论列表
     * 支持多种排序方式，未登录用户也可查看
     */
    @GetMapping("/article/{articleId}")
    public Result<List<ArticleCommentResponse>> getArticleComments(
            @PathVariable @NotNull Long articleId,
            @RequestParam(defaultValue = "true") Boolean topLevelOnly,
            @RequestParam(defaultValue = "latest") String sortType,
            @RequestParam(required = false) Long rootId) {
        
        log.info("获取文章评论列表: articleId={}, topLevelOnly={}, sortType={}", 
                articleId, topLevelOnly, sortType);
        
        try {
            // 构建查询请求
            ArticleCommentListRequest request = new ArticleCommentListRequest();
            request.setArticleId(articleId);
            request.setTopLevelOnly(topLevelOnly);
            request.setSortType(sortType);
            request.setRootId(rootId);
            
            // 查询评论列表
            List<ArticleCommentResponse> comments = userCommentService.getArticleComments(request);
            
            return Result.success("获取评论列表成功", comments);
        } catch (Exception e) {
            log.error("获取文章评论列表失败: articleId={}", articleId, e);
            return Result.error("获取评论列表失败：" + e.getMessage());
        }
    }


    /**
     * 获取文章评论树形结构（推荐使用）
     * 一次性加载避免N+1查询问题
     * 未登录用户也可查看
     */
    @GetMapping("/tree")
    public Result<PageResult<ArticleCommentResponse>> getCommentTree(@Valid CommentTreeRequest request) {
        log.info("获取评论树形结构: articleId={}, maxLevel={}, childrenLimit={}", 
                request.getArticleId(), request.getMaxLevel(), request.getChildrenLimit());
        
        try {
            PageResult<ArticleCommentResponse> commentTree = userCommentService.getCommentTree(request);
            log.info("获取评论树成功: 总数={}, 当前页数量={}", 
                    commentTree.getTotal(), commentTree.getRecords().size());
            return Result.success("获取评论树成功", commentTree);
        } catch (Exception e) {
            log.error("获取评论树失败: articleId={}", request.getArticleId(), e);
            return Result.error("获取评论树失败：" + e.getMessage());
        }
    }

    /**
     * 创建评论
     * 需要登录
     */
    @PostMapping("/create")
    @SaCheckLogin
    @RateLimit(count = 10, time = 60, limitType = LimitType.USER, message = "评论过于频繁，请稍后再试")
    public Result<ArticleCommentResponse> createComment(@RequestBody @Valid CommentCreateRequest request) {
        Long userId = StpUtil.getLoginIdAsLong();
        // 获取当前用户ID（如果已登录）
        try {
            if (StpUtil.isLogin()) {
                userId = StpUtil.getLoginIdAsLong();
            }
        } catch (Exception e) {
            // 未登录状态，继续执行
            return Result.error("用户未登录");
        }
        String clientIp = getClientIp();
        String userAgent = getRequest().getHeader("User-Agent");
        
        log.info("创建评论: userId={}, articleId={}, parentId={}", userId, request.getArticleId(), request.getParentId());
        
        try {
            ArticleCommentResponse response = userCommentService.createComment(request, userId, clientIp, userAgent);
            log.info("评论创建成功: commentId={}", response.getId());
            return Result.success("评论发表成功", response);
        } catch (Exception e) {
            log.error("创建评论失败: userId={}, articleId={}", userId, request.getArticleId(), e);
            return Result.error("发表评论失败：" + e.getMessage());
        }
    }

    /**
     * 点赞/取消点赞评论
     * 需要登录
     */
    @PostMapping("/like")
    @SaCheckLogin
    public Result<CommentLikeResponse> likeComment(@RequestBody @Valid CommentLikeRequest request) {
        Long userId = StpUtil.getLoginIdAsLong();
        log.info("评论点赞操作: userId={}, commentId={}, liked={}", userId, request.getCommentId(), request.getLiked());
        
        try {
            CommentLikeResponse response = userCommentService.likeComment(request, userId);
            return Result.success(response.getMessage(), response);
        } catch (Exception e) {
            log.error("评论点赞操作失败: userId={}, commentId={}", userId, request.getCommentId(), e);
            return Result.error("操作失败：" + e.getMessage());
        }
    }

    /**
     * 获取评论详情
     * 未登录用户也可查看，但不显示点赞状态
     */
    @GetMapping("/{commentId}")
    public Result<ArticleCommentResponse> getCommentDetail(@PathVariable @NotNull Long commentId) {
        log.info("获取评论详情: commentId={}", commentId);
        
        try {
            // 获取当前用户ID（如果已登录）
            Long userId = null;
            try {
                if (StpUtil.isLogin()) {
                    userId = StpUtil.getLoginIdAsLong();
                }
            } catch (Exception e) {
                log.error("获取评论详情失败: commentId={}", commentId, e);
                log.error("用户未登录，忽略异常");
                // 用户未登录，忽略异常
            }
            
            ArticleCommentResponse response = userCommentService.getCommentDetail(commentId, userId);
            return Result.success("获取评论详情成功", response);
        } catch (Exception e) {
            log.error("获取评论详情失败: commentId={}", commentId, e);
            return Result.error("获取评论详情失败：" + e.getMessage());
        }
    }

    /**
     * 删除评论
     * 需要登录，只能删除自己的评论
     */
    @DeleteMapping("/{commentId}")
    @SaCheckLogin
    public Result<Void> deleteComment(@PathVariable @NotNull Long commentId) {
        Long userId = StpUtil.getLoginIdAsLong();
        
        log.info("删除评论: userId={}, commentId={}", userId, commentId);
        
        try {
            boolean success = userCommentService.deleteComment(commentId, userId);
            if (success) {
                return Result.success("评论删除成功");
            } else {
                return Result.error("评论删除失败");
            }
        } catch (Exception e) {
            log.error("删除评论失败: userId={}, commentId={}", userId, commentId, e);
            return Result.error("删除评论失败：" + e.getMessage());
        }
    }

    /**
     * 获取评论统计信息
     * 未登录用户也可查看，但不显示个人点赞状态
     */
    @GetMapping("/{commentId}/stats")
    public Result<CommentStatsResponse> getCommentStats(@PathVariable @NotNull Long commentId) {
        log.info("获取评论统计: commentId={}", commentId);
        
        try {
            CommentStatsResponse response = userCommentService.getCommentStats(commentId);
            return Result.success("获取统计信息成功", response);
        } catch (Exception e) {
            log.error("获取评论统计失败: commentId={}", commentId, e);
            return Result.error("获取统计信息失败：" + e.getMessage());
        }
    }

    /**
     * 检查用户是否可以评论指定文章
     * 需要登录
     */
    @GetMapping("/check-commentable")
    @SaCheckLogin
    public Result<Boolean> checkCommentable(@RequestParam @NotNull Long articleId) {
        Long userId = StpUtil.getLoginIdAsLong();
        
        log.info("检查用户评论权限: userId={}, articleId={}", userId, articleId);
        
        try {
            boolean canComment = userCommentService.canUserComment(articleId, userId);
            return Result.success("检查完成", canComment);
        } catch (Exception e) {
            log.error("检查评论权限失败: userId={}, articleId={}", userId, articleId, e);
            return Result.error("检查失败：" + e.getMessage());
        }
    }

    /**
     * 获取当前请求对象
     */
    private HttpServletRequest getRequest() {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        return attributes != null ? attributes.getRequest() : null;
    }

    /**
     * 获取客户端IP地址
     */
    private String getClientIp() {
        HttpServletRequest request = getRequest();
        if (request == null) {
            return "unknown";
        }

        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }

        // 如果是多级代理，取第一个IP
        if (ip != null && ip.contains(",")) {
            ip = ip.substring(0, ip.indexOf(",")).trim();
        }

        return ip;
    }

    // ==================== 评论图片上传功能 ====================

    /**
     * 上传评论图片
     * 支持临时上传，用于评论发表前的图片预上传
     * 需要登录
     */
    @PostMapping("/upload-image")
    @SaCheckLogin
    public Result<CommentImageUploadResponse> uploadCommentImage(
            @RequestParam("file") MultipartFile file,
            @RequestParam(value = "uploadToken", required = false) String uploadToken) {
        
        Long userId = StpUtil.getLoginIdAsLong();
        log.info("上传评论图片: userId={}, fileName={}, fileSize={}, uploadToken={}", 
                userId, file.getOriginalFilename(), file.getSize(), uploadToken);
        
        try {
            // 验证文件
            if (file.isEmpty()) {
                return Result.error("请选择要上传的文件");
            }

            // 上传图片到临时存储
            CommentImageUploadResponse response = commentImageService.uploadCommentImage(file, userId, uploadToken);
            
            if (response.getSuccess()) {
                log.info("评论图片上传成功: userId={}, tempImageId={}", userId, response.getTempImageId());
                return Result.success(response.getMessage(), response);
            } else {
                log.warn("评论图片上传失败: userId={}, message={}", userId, response.getMessage());
                return Result.error(response.getMessage());
            }
            
        } catch (Exception e) {
            log.error("评论图片上传异常: userId={}", userId, e);
            return Result.error("图片上传失败：" + e.getMessage());
        }
    }

    /**
     * 获取用户的临时图片列表
     * 用于查看已上传但未关联到评论的图片
     * 需要登录
     */
    @GetMapping("/temp-images")
    @SaCheckLogin
    public Result<List<CommentImageInfo>> getUserTempImages(
            @RequestParam(value = "uploadToken", required = false) String uploadToken) {
        
        Long userId = StpUtil.getLoginIdAsLong();
        log.info("获取用户临时图片: userId={}, uploadToken={}", userId, uploadToken);
        
        try {
            List<CommentImageInfo> tempImages = commentImageService.getUserTempImages(userId, uploadToken);
            return Result.success("获取临时图片成功", tempImages);
        } catch (Exception e) {
            log.error("获取用户临时图片失败: userId={}", userId, e);
            return Result.error("获取临时图片失败：" + e.getMessage());
        }
    }

    /**
     * 删除评论图片
     * 只能删除自己上传的图片
     * 需要登录
     */
    @DeleteMapping("/images/{imageId}")
    @SaCheckLogin
    public Result<Void> deleteCommentImage(@PathVariable @NotNull Long imageId) {
        Long userId = StpUtil.getLoginIdAsLong();
        log.info("删除评论图片: userId={}, imageId={}", userId, imageId);
        
        try {
            boolean success = commentImageService.deleteCommentImage(imageId, userId);
            if (success) {
                return Result.success("图片删除成功");
            } else {
                return Result.error("图片删除失败");
            }
        } catch (Exception e) {
            log.error("删除评论图片失败: userId={}, imageId={}", userId, imageId, e);
            return Result.error("删除图片失败：" + e.getMessage());
        }
    }

    /**
     * 获取评论的图片列表
     * 未登录用户也可查看
     */
    @GetMapping("/{commentId}/images")
    public Result<List<CommentImageInfo>> getCommentImages(@PathVariable @NotNull Long commentId) {
        log.info("获取评论图片: commentId={}", commentId);
        
        try {
            List<CommentImageInfo> images = commentImageService.getCommentImages(commentId);
            return Result.success("获取评论图片成功", images);
        } catch (Exception e) {
            log.error("获取评论图片失败: commentId={}", commentId, e);
            return Result.error("获取评论图片失败：" + e.getMessage());
        }
    }

    /**
     * 批量获取多个评论的图片列表（性能优化）
     * 前端可以一次性获取所有评论的图片，避免N+1查询问题
     * 未登录用户也可查看
     */
    @PostMapping("/batch-images")
    public Result<Map<Long, List<CommentImageInfo>>> getBatchCommentImages(
            @RequestBody @NotNull List<Long> commentIds) {
        
        // 限制批量查询的数量，防止请求过大
        if (commentIds.size() > 100) {
            return Result.error("批量查询评论图片数量不能超过100个");
        }
        
        log.info("批量获取评论图片: commentIds={}, count={}", commentIds, commentIds.size());
        
        try {
            Map<Long, List<CommentImageInfo>> imagesMap = commentImageService.getBatchCommentImages(commentIds);
            return Result.success("批量获取评论图片成功", imagesMap);
        } catch (Exception e) {
            log.error("批量获取评论图片失败: commentIds={}", commentIds, e);
            return Result.error("批量获取评论图片失败：" + e.getMessage());
        }
    }

    /**
     * 生成上传令牌
     * 用于批量上传图片的会话管理
     * 需要登录
     */
    @PostMapping("/generate-upload-token")
    @SaCheckLogin
    public Result<String> generateUploadToken() {
        Long userId = StpUtil.getLoginIdAsLong();
        
        try {
            String uploadToken = commentImageService.generateUploadToken(userId);
            log.info("生成上传令牌: userId={}, token={}", userId, uploadToken);
            return Result.success("生成上传令牌成功", uploadToken);
        } catch (Exception e) {
            log.error("生成上传令牌失败: userId={}", userId, e);
            return Result.error("生成上传令牌失败：" + e.getMessage());
        }
    }

    /**
     * 验证文件是否为有效的评论图片
     * 用于前端上传前的预验证
     * 需要登录
     */
    @PostMapping("/validate-image")
    @SaCheckLogin
    public Result<Boolean> validateCommentImage(@RequestParam("file") MultipartFile file) {
        try {
            boolean isValid = commentImageService.isValidCommentImage(file);
            return Result.success("文件验证完成", isValid);
        } catch (Exception e) {
            log.error("文件验证失败", e);
            return Result.error("文件验证失败：" + e.getMessage());
        }
    }
}
